/* 
 * File:   NLLibrary.h
 * Author: sergey
 *
 * Created on 13 Декабрь 2009 г., 16:48
 */

#ifndef _NLLIBRARY_H
#define	_NLLIBRARY_H

#include "LibraryInterface.h"
#include "BooleanFunction.h"
#include <vector>
#include <iostream>

/*
 * NLLIbrary - класс для хранения библиотеки в 4 раза меньше полного хранения
 * всех функций.
 */
template <typename LIBINFO>
class NLLibrary:public LibraryInterface {
public:
    NLLibrary() {}
    ~NLLibrary() { }
    inline bool isSet(const UInt64 f) {
        UInt8 s;
        get(f,s);
        if (s == 0) return false;
        return true;
    }
    inline void set(const UInt64 f, const UInt8 s) {
        UInt64 n;
        getNumberInData(f, n);   
        if ((n & 1) == 0) {
            data[n >> 1] = (0x0F & data[n >> 1]) ^ (s << 4);
        } else {
            data[n >> 1] = (0xF0 & data[n >> 1]) ^ s;
        }        
    }
    inline void get(const UInt32 f, UInt8 &s) {
        UInt64 n;
        getNumberInData(f, n);
        if ((n & 1) == 0) {
            s = data[n >> 1] >> 4;
        } else {
            s = data[n >> 1] & 0xF;
        }
    }
    static inline void getNumberInData(const UInt64 f, UInt64 &num) {
        enum {
            lm = 1 << (LIBINFO::aC - 1),
            rm = 1 << ((LIBINFO::aC >> 1) - 1)
        };
        if ((f & lm) == 0) {
            num = f;            
        } else {
            if ((f & rm) == 0) {
                num = f;
                BooleanFunction<LIBINFO>::template negation<0>(num);
            } else {
                num = f;
                BooleanFunction<LIBINFO>::template derivative2<0>(num);
            }
        }
    }
    void load(const std::string filename) {
        data.resize(LIBINFO::fC >> 2);
        this->readFileOpen(filename.c_str());
        this->readIntVector(data, data.size());
        this->readFileClose();
    }
    void save(const std::string filename) {        
        this->writeFileOpen(filename.c_str());
        this->reset();
        this->writeIntVector(data);
        this->writeFileClose();
    }

private:
    std::vector<UInt8> data;
};

#endif	/* _NLLIBRARY_H */
